boolean reading = false;
boolean flashstate = false;
boolean fadestate = false;
unsigned long flashtimer;
unsigned long fadetimer;
#define red 9
#define green 10
#define blue 11
#define SIZE    255
#define DELAY    0
#define HUE_MAX  6.0
#define HUE_DELTA 0.01
int MIN_TEMP = 18;
int MAX_TEMP = 30;
long rgb[3];
long rgbval;
// for reasons unknown, if value !=0, the LED doesn't light. Hmm ...
// and saturation seems to be inverted
float hue=0.0, saturation=1, value=1;
long bright[3] = { 
  255, 255, 255};
//long bright[3] = { 256, 256, 256};
long k;

String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete
String ledcolour = "red";

void setup(){
  Serial.begin(9600);
  inputString.reserve(200);
  //Pins 10,11,12 & 13 are used by the ethernet shield

  for (k=0; k<3; k++) {
    pinMode(red + k, OUTPUT);
    rgb[k]=0;
    analogWrite(red + k, rgb[k] * bright[k]/256);
  }

  //Ethernet.begin(mac);

}

void loop(){

  // listen for incoming clients, and process qequest.
  if (stringComplete) {
    int i, count; 
    for (i=0, count=0; inputString[i]; i++) 
      count += (inputString[i] == ','); 

    String newData[count];

    for(int i =0; i < count;i++){
      int firstpos = inputString.indexOf(",");
      newData[i] = inputString.substring(0,firstpos);
      inputString = inputString.substring(firstpos+1,inputString.length());
    }
    inputString = "";
    stringComplete = false;

    if (newData[0] == "temp"){
      MIN_TEMP = convint(newData[2]);
      MAX_TEMP = convint(newData[3]);
      float temperature = constrain(convint(newData[1]), MIN_TEMP, MAX_TEMP);

      float deltaTemp = (MAX_TEMP - MIN_TEMP);
      float deltaHue = 4 - 0;
      hue = map((temperature - MIN_TEMP) * 100, 0, deltaTemp * 100, deltaHue * 100, 0) / 100.0;
      rgbval=HSV_to_RGB(hue, saturation, value);
      rgb[0] = (rgbval & 0x00FF0000) >> 16; // there must be better ways
      rgb[1] = (rgbval & 0x0000FF00) >> 8;
      rgb[2] = rgbval & 0x000000FF; 
    }else{

    rgb[0] = constrain(convint(newData[0]),0,255);
    rgb[1] = constrain(convint(newData[1]),0,255);
    rgb[2] = constrain(convint(newData[2]),0,255);          
    Serial.println("Colour Values:");
    Serial.println(rgb[0]);
    Serial.println(rgb[1]);
    Serial.println(rgb[2]);
    }
  }

  for (k=0; k<3; k++) { // for all three colours
    analogWrite(red + k, rgb[k] * bright[k]/256);
  }

}
int convint(String Data){
  char carray2[Data.length() +1];
  Data.toCharArray(carray2,sizeof(carray2));
  return atoi(carray2); 
}

long HSV_to_RGB( float h, float s, float v ) {
  /* modified from Alvy Ray Smith's site: http://www.alvyray.com/Papers/hsv2rgb.htm */
  // H is given on [0, 6]. S and V are given on [0, 1].
  // RGB is returned as a 24-bit long #rrggbb
  int i;
  float m, n, f;

  // not very elegant way of dealing with out of range: return black
  if ((s<0.0) || (s>1.0) || (v<1.0) || (v>1.0)) {
    return 0L;
  }

  if ((h < 0.0) || (h > 6.0)) {
    return long( v * 255 ) + long( v * 255 ) * 256 + long( v * 255 ) * 65536;
  }
  i = floor(h);
  f = h - i;
  if ( !(i&1) ) {
    f = 1 - f; // if i is even
  }
  m = v * (1 - s);
  n = v * (1 - s * f);
  switch (i) {
  case 6:
  case 0: 
    return long(v * 255 ) * 65536 + long( n * 255 ) * 256 + long( m * 255);
  case 1: 
    return long(n * 255 ) * 65536 + long( v * 255 ) * 256 + long( m * 255);
  case 2: 
    return long(m * 255 ) * 65536 + long( v * 255 ) * 256 + long( n * 255);
  case 3: 
    return long(m * 255 ) * 65536 + long( n * 255 ) * 256 + long( v * 255);
  case 4: 
    return long(n * 255 ) * 65536 + long( m * 255 ) * 256 + long( v * 255);
  case 5: 
    return long(v * 255 ) * 65536 + long( m * 255 ) * 256 + long( n * 255);
  }
}


void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read(); 
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    } 
  }
}




